/****************************************************************************
 * Copyright (C) 2012 Dj_Skual
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ****************************************************************************/
#include "Explorer.h"
#include "MainMenu.h"
#include "TaskBar.hpp"
#include "../System/sys.h"
#include "../System/input.h"
#include "../System/video.h"
#include "../Themes/CTheme.h"
#include "../Controls/Application.h"
#include "../Tools/StartUpProcess.h"
#include "../Prompts/SearchWindow.h"
#include "../Prompts/PromptWindows.h"
#include "../Network/Updates/Update.h"
#include "../BootHomebrew/HomebrewMenu.h"
#include "../Miis/MiiInstaller.h"
#include "../DeviceControls/DevicesSwap.h"
#include "../SoundOperations/MusicPlayer.h"

MainMenu *MainMenu::instance = NULL;

MainMenu::MainMenu()
	: GuiFrame(screenwidth, screenheight)
{
	diplayed = false;
	
	updateRequested = false;
	updateUrl = "";
	
	BtnSoundClick = Resources::GetSound("button_click.wav");
	BtnSoundOver = Resources::GetSound("button_over.wav");
	BtnSoundClick->SetVolume(Settings.SFXVolume);
	BtnSoundOver->SetVolume(Settings.SFXVolume);
	
	trigA = new SimpleGuiTrigger(-1, WiiControls.ClickButton | ClassicControls.ClickButton << 16, GCControls.ClickButton);
	
	bgData = Resources::GetImageData(Settings.Widescreen ? "menu_wbackground.png" : "menu_background.png");
	bgImg = new GuiImage(bgData);
	
	ManageTT = new GuiTooltip(tr( "Manage All" ));
	ManageTT->SetAlignment(thAlign("left - manageAll btn tooltip align hor") | thInt("top - manageAll btn tooltip align ver"));
	ManageTT->SetPosition(thInt("24 - manageAll btn tooltip pos x"), thInt("-30 - manageAll btn tooltip pos y"));
	ManageTT->SetAlpha(thInt("255 - tooltip alpha"));
	
	ManageBtn = new PictureButton("menu_button_switch.png", "menu_button_switch_over.png", BtnSoundClick, BtnSoundOver);
	ManageBtn->SetAlignment(thAlign("left - manageAll btn align hor") | thInt("top - manageAll btn align ver"));
	ManageBtn->SetPosition(thInt("16 - manageAll btn pos x"), thInt("355 - managAll btn pos y"));
	ManageBtn->SetTooltip(ManageTT);
	ManageBtn->SetTrigger(trigA);
	ManageBtn->Clicked.connect(this, &MainMenu::OnManageButtonClick);
	
	SettingsTT = new GuiTooltip(tr("Settings"));
	SettingsTT->SetAlignment(thAlign("left - settings btn tooltip align hor") | thInt("top - settings btn tooltip align ver"));
	SettingsTT->SetPosition(thInt("65 - settings btn tooltip pos x"), thInt("-30 - settings btn tooltip pos y"));
	SettingsTT->SetAlpha(thInt("255 - tooltip alpha"));
	
	SettingsBtn = new PictureButton("menu_button_settings.png", "menu_button_settings_over.png", BtnSoundClick, BtnSoundOver);
	SettingsBtn->SetAlignment(thAlign("left - settings btn align hor") | thInt("top - settings btn align ver"));
	SettingsBtn->SetPosition(thInt("64 - settings btn pos x"), thInt("371 - settings btn pos y"));
	SettingsBtn->SetTooltip(SettingsTT);
	SettingsBtn->SetTrigger(trigA);
	SettingsBtn->Clicked.connect(this, &MainMenu::OnSettingsButtonClick);
	
	HomebrewTT = new GuiTooltip(tr( "Homebrew Launcher" ));
	HomebrewTT->SetAlignment(thAlign("right - homebrew btn tooltip align hor") | thInt("top - homebrew btn tooltip align ver"));
	HomebrewTT->SetPosition(thInt("-65 - homebrew btn tooltip pos x"), thInt("-30 - homebrew btn tooltip pos y"));
	HomebrewTT->SetAlpha(thInt("255 - tooltip alpha"));
	
	HomebrewBtn = new PictureButton("menu_button_wii.png", "menu_button_wii_over.png", BtnSoundClick, BtnSoundOver);
	HomebrewBtn->SetAlignment(thAlign("left - homebrew btn align hor") | thInt("top - homebrew btn align ver"));
	HomebrewBtn->SetPosition(thInt("489 - homebrew btn pos x"), thInt("371 - homebrew btn pos y"));
	HomebrewBtn->SetTooltip(HomebrewTT);
	HomebrewBtn->SetTrigger(trigA);
	HomebrewBtn->Clicked.connect(this, &MainMenu::OnHomebrewButtonClick);
	
	MusicPlayerTT = new GuiTooltip(tr( "Music Player" ));
	MusicPlayerTT->SetAlignment(thAlign("right - music btn tooltip align hor") | thInt("top - music btn tooltip align ver"));
	MusicPlayerTT->SetPosition(thInt("-24 - music btn tooltip pos x"), thInt("-30 - music btn tooltip pos y"));
	MusicPlayerTT->SetAlpha(thInt("255 - tooltip alpha"));
	
	MusicPlayerBtn = new PictureButton("menu_button_music.png", "menu_button_music_over.png", BtnSoundClick, BtnSoundOver);
	MusicPlayerBtn->SetAlignment(thAlign("left - music btn align hor") | thInt("top - music btn align ver"));
	MusicPlayerBtn->SetPosition(thInt("576 - music btn pos x"), thInt("355 - music btn pos y"));
	MusicPlayerBtn->SetTooltip(MusicPlayerTT);
	MusicPlayerBtn->SetTrigger(trigA);
	MusicPlayerBtn->Clicked.connect(this, &MainMenu::OnMusicButtonClick);
	
	SdCardImgData = Resources::GetImageData("menu_button_sdcard.png");
	SdCardImgGrayData = Resources::GetImageData("menu_button_sdcard_gray.png");
	SdCardImg = new GuiImage(SdCardImgData);
	SdCardImgGray = new GuiImage(SdCardImgGrayData);
	
	SdCardTT = new GuiTooltip(tr( "Reload SD" ));
	SdCardTT->SetAlignment(thAlign("left - sd card btn tooltip align hor") | thInt("top - sd card btn tooltip align ver"));
	SdCardTT->SetPosition(thInt("15 - sd card btn tooltip pos x"), thInt("-30 - sd card btn tooltip pos y"));
	SdCardTT->SetAlpha(thInt("255 - tooltip alpha"));
	
	bool sd_inserted = DeviceHandler::Instance()->IsInserted(SD);
	SdCardBtn = new PictureButton("menu_button_sdcard.png", "menu_button_sdcard_over.png", BtnSoundClick, BtnSoundOver);
	SdCardBtn->SetAlignment(thAlign("left - sd card btn align hor") | thInt("top - sd card btn align ver"));
	SdCardBtn->SetPosition(thInt("160 - sd card btn pos x"), thInt("395 - sd card btn pos y"));
	SdCardBtn->SetImage(sd_inserted ? SdCardImg : SdCardImgGray);
	SdCardBtn->SetState(sd_inserted ? STATE_DEFAULT : STATE_DISABLED);
	SdCardBtn->SetTooltip(SdCardTT);
	SdCardBtn->SetTrigger(trigA);
	SdCardBtn->Clicked.connect(this, &MainMenu::OnSdCardButtonClick);
	
	clock = new Clock();
	
	DevicesSwap::Instance()->Swapped.connect(this, &MainMenu::OnDevicesStateChange);
	
	EffectFinished.connect(this, &MainMenu::OnFadeEffectFinish);
}

MainMenu::~MainMenu()
{
	RemoveAll();
	
	delete bgImg;
	Resources::Remove(bgData);
	
	delete SdCardImg;
	delete SdCardImgGray;
	
	Resources::Remove(SdCardImgData);
	Resources::Remove(SdCardImgGrayData);
	
	delete ManageTT;
	delete SettingsTT;
	delete HomebrewTT;
	delete MusicPlayerTT;
	delete SdCardTT;
	
	delete ManageBtn;
	delete SettingsBtn;
	delete HomebrewBtn;
	delete MusicPlayerBtn;
	delete SdCardBtn;
	
	Resources::Remove(BtnSoundClick);
	Resources::Remove(BtnSoundOver);
	
	if(clock)
		delete clock;
	
	TaskBar::DestroyInstance();
	Explorer::DestroyInstance();
	
	delete trigA;
}

void MainMenu::show()
{
	if(Application::Instance()->isReloading())
	{
		SettingsMenu *settingsMenu = new SettingsMenu();
		settingsMenu->Closing.connect(this, &MainMenu::OnMenusClosing);
		settingsMenu->ForcedClosing.connect(this, &MainMenu::OnSettingsForcedClosing);
		
		Application::Instance()->SetUpdateOnly(settingsMenu);
		Application::Instance()->Append(settingsMenu);
		
		return;
	}
	
	Append(bgImg);
	Append(clock);
	Append(ManageBtn);
	Append(SettingsBtn);
	Append(HomebrewBtn);
	Append(MusicPlayerBtn);
	Append(SdCardBtn);
	
	TaskBar::Instance()->show();
	Explorer::Instance()->show();
	
	if(Settings.StartUp)
	{
		StartUpProcess::Instance()->SetTxt("Complete.\n\n");
		usleep(1);
		StartUpProcess::DestroyInstance();
	}
	
	diplayed = true;
	SetEffect(EFFECT_FADE, 20);
	Application::Instance()->SetGuiInputUpdate(false);
}

void MainMenu::hide()
{
	if(SearchWindow::Instance()->IsRunning())
	{
		SearchWindow::Instance()->Hide();
		TaskBar::Instance()->UpdateSearchButton();
	}
	
	TaskBar::Instance()->hide();
	Explorer::Instance()->hide();
	
	diplayed = false;
	SetEffect(EFFECT_FADE, -20);
	Application::Instance()->SetGuiInputUpdate(false);
}

void MainMenu::OnFadeEffectFinish(GuiElement *element UNUSED)
{
	Application::Instance()->SetGuiInputUpdate(true);
	if(!diplayed)
	{
		Application::Instance()->Remove(TaskBar::Instance());
		Application::Instance()->Remove(Explorer::Instance());
		RemoveAll();
	}
	
	if(!Settings.UpdateChecked)
	{
		Settings.UpdateChecked = true;
		
		Mii::Fix_DB();
		
		if(Settings.AutoConnect)
		{
			AutoUpdateCheckTask * autoUpdateTask = new AutoUpdateCheckTask();
			autoUpdateTask->UpdateCheckEnd.connect(this, &MainMenu::OnUpdateCheckEnd);
		}
	}
}

void MainMenu::OnManageButtonClick(GuiButton *sender UNUSED, int pointer UNUSED, const POINT &p UNUSED)
{
	ShowMsg("Under Development...", 0);
}

void MainMenu::OnSettingsButtonClick(GuiButton *sender UNUSED, int pointer UNUSED, const POINT &p UNUSED)
{
	if (!Settings.GodMode && (Settings.ParentalBlocks & BLOCK_GLOBAL_SETTINGS))
	{
		WindowPrompt(tr( "Permission denied." ), tr( "Console must be unlocked for this option." ), tr( "OK" ));
		return;
	}
	
	hide();
	
	SettingsMenu *settingsMenu = new SettingsMenu();
	settingsMenu->Closing.connect(this, &MainMenu::OnMenusClosing);
	settingsMenu->ForcedClosing.connect(this, &MainMenu::OnSettingsForcedClosing);
	
	Application::Instance()->SetUpdateOnly(settingsMenu);
	Application::Instance()->Append(settingsMenu);
}

void MainMenu::OnHomebrewButtonClick(GuiButton *sender UNUSED, int pointer UNUSED, const POINT &p UNUSED)
{
	if (!Settings.GodMode && (Settings.ParentalBlocks & BLOCK_HBC_MENU))
	{
		WindowPrompt(tr( "Permission denied." ), tr( "Console must be unlocked for this option." ), tr( "OK" ));
		return;
	}
	
	hide();
	
	HomebrewMenu *homebrewMenu = new HomebrewMenu();
	homebrewMenu->Closing.connect(this, &MainMenu::OnMenusClosing);
	
	Application::Instance()->SetUpdateOnly(homebrewMenu);
	Application::Instance()->Append(homebrewMenu);
}

void MainMenu::OnMusicButtonClick(GuiButton *sender UNUSED, int pointer UNUSED, const POINT &p UNUSED)
{
	MusicPlayer::Instance()->Show();
}

void MainMenu::OnDevicesStateChange(int device, bool inserted)
{
	bool reload = false;
	
	if(device == DevicesSwap::SD)
	{
		if(inserted)
		{
			SdCardBtn->SetImage(SdCardImg);
			SdCardBtn->SetState(STATE_DEFAULT);
		}
		else
		{
			SdCardBtn->SetImage(SdCardImgGray);
			SdCardBtn->SetState(STATE_DISABLED);
			
			if ((Settings.LoadedBrowser == SAVE_BROWSER) ||
				(Settings.LoadedBrowser == MII_BROWSER) ||
				(Settings.LoadedBrowser == GC_BROWSER))
				return;
			
			int browsedDevice = -1;
			if ((Settings.LoadedBrowser == ESAVE_BROWSER) ||
				(Settings.LoadedBrowser == EMII_BROWSER))
				browsedDevice = DeviceHandler::PathToDriveType(CurrentBrowser()->GetCurrentPath());
			else
				browsedDevice = DeviceHandler::PathToDriveType(CurrentBrowser()->GetRootDir());
			
			if(browsedDevice != SD)
				return;
			
			for(int dev = USB1; dev <= USB9; ++dev)
			{
				if(!DeviceHandler::Instance()->IsInserted(dev))
					continue;
				
				Settings.LastUsedPath = DeviceName[dev];
				Settings.LastUsedPath += ":/";
				break;
			}
			
			reload = true;
		}
	}
	else if(device == DevicesSwap::USB0 ||
			device == DevicesSwap::USB1)
	{
		if(!inserted)
		{
			if ((Settings.LoadedBrowser == SAVE_BROWSER) ||
				(Settings.LoadedBrowser == MII_BROWSER) ||
				(Settings.LoadedBrowser == GC_BROWSER))
				return;
			
			int browsedDevice = -1;
			if ((Settings.LoadedBrowser == ESAVE_BROWSER) ||
				(Settings.LoadedBrowser == EMII_BROWSER))
				browsedDevice = DeviceHandler::PathToDriveType(CurrentBrowser()->GetCurrentPath());
			else
				browsedDevice = DeviceHandler::PathToDriveType(CurrentBrowser()->GetRootDir());
			
			int browsedPort = -1;
			if(browsedDevice != SD)
				browsedPort = DeviceHandler::Instance()->PartToPort(browsedDevice);
			
			if(device == DevicesSwap::USB0)
				DeviceHandler::Instance()->UnMountUSBPort0();
			else
				DeviceHandler::Instance()->UnMountUSBPort1();
			
			if(browsedDevice == SD)
				return;
			
			if(device == DevicesSwap::USB0 && browsedPort == 1)
				return;
			else if(device == DevicesSwap::USB1 && browsedPort == 0)
				return;
			
			for(int dev = SD; dev <= USB9; ++dev)
			{
				if(!DeviceHandler::Instance()->IsInserted(dev))
					continue;
				
				Settings.LoadedBrowser = SDUSB_BROWSER;
				Settings.LastUsedPath = DeviceName[dev];
				Settings.LastUsedPath += ":/";
				break;
			}
			
			reload = true;
		}
	}
	else if(device == DevicesSwap::GCA ||
			device == DevicesSwap::GCB)
	{
		if(!inserted)
		{
			if(Settings.LoadedBrowser != GC_BROWSER)
				return;
			
			if((device == DevicesSwap::GCA) && CurrentBrowser()->GetCurrentPath().compare("gca"))
				return;
			else if((device == DevicesSwap::GCB) && CurrentBrowser()->GetCurrentPath().compare("gcb"))
				return;
			
			for(int dev = SD; dev <= USB9; ++dev)
			{
				if(!DeviceHandler::Instance()->IsInserted(dev))
					continue;
				
				Settings.LoadedBrowser = SDUSB_BROWSER;
				Settings.LastUsedPath = DeviceName[dev];
				Settings.LastUsedPath += ":/";
				break;
			}
			
			reload = true;
		}
	}
	
	if(reload)
	{
		if(DevicesSwap::Instance()->IsWaiting())
			DevicesSwap::Instance()->SetExplorerReload();
		else
		{	
			Explorer::Instance()->Reload();
			TaskBar::Instance()->UpdateAllButtons();
			
			CurrentBrowser()->FilterList();
			if(SearchWindow::Instance()->IsRunning())
				SearchWindow::Instance()->Refresh();
		}
	}
}

void MainMenu::OnSdCardButtonClick(GuiButton *sender UNUSED, int pointer UNUSED, const POINT &p UNUSED)
{
	Application::Instance()->ResetPads();
	
	Settings.Save();
	
	if(!MusicPlayer::Instance()->IsStopped())
		MusicPlayer::Instance()->Pause();

	DeviceHandler::Instance()->UnMountSD();
	DeviceHandler::Instance()->MountSD();
	
	std::string usedPath = Settings.LastUsedPath;
	int browser = Settings.LoadedBrowser;
	
	gprintf("\tLoading config...%s\n", Settings.Load() ? "done" : "failed");
	gprintf("\tLoading language...%s\n", Settings.LoadLanguage(Settings.LanguageFile, CONSOLE_DEFAULT) ? "done" : "failed");
	gprintf("\tLoading font...%s\n", Theme::LoadFont(Settings.CustomFontPath) ? "done" : "failed (using default)");
	gprintf("\tLoading theme...%s\n", Theme::Load(Settings.Theme) ? "done" : "failed (using default)");
	
	if(!MusicPlayer::Instance()->IsStopped())
		MusicPlayer::Instance()->Resume();
	
	Settings.LastUsedPath = usedPath;
	Settings.LoadedBrowser = browser;
	
	bool checksd = false;
	if (Settings.LoadedBrowser == SDUSB_BROWSER ||
		Settings.LoadedBrowser == ESAVE_BROWSER ||
		Settings.LoadedBrowser == EMII_BROWSER)
		checksd = true;
	
	if(checksd && !usedPath.compare(0, 2, "sd"))
	{
		Explorer::Instance()->Reload();
		TaskBar::Instance()->UpdateSearchButton();
		
		CurrentBrowser()->FilterList();
		if(SearchWindow::Instance()->IsRunning())
			SearchWindow::Instance()->Refresh();
	}
}

void MainMenu::OnMenusClosing(GuiFrame *menu UNUSED)
{
	if(Application::Instance()->isReloading())
		return;
	
	show();
}

void MainMenu::OnSettingsForcedClosing(SettingsMenu * menu)
{
	Application::Instance()->Remove(menu);
	Application::Instance()->UnsetUpdateOnly(menu);
	delete menu;
	
	Application::Instance()->Reload();
}

void MainMenu::OnUpdateCheckEnd(AutoUpdateCheckTask * task, std::string url)
{
	delete task;
	
	if(url.empty())
		return;
	
	updateRequested = true;
	updateUrl = url;
}

void MainMenu::ExecuteUpdate()
{
	updateRequested = false;
	
	if(UpdateApp(updateUrl.c_str()))
	{
		if(WindowPrompt(tr("Update successfully finished"), tr("Do you want to reboot now ?"), tr("Yes"), tr("No")))
			RebootApp();
	}
	
	updateUrl = "";
}

